-
Notifications
You must be signed in to change notification settings - Fork 8
Feat/segmentation service -> master #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…ions to ensure backward compatibility
| namespace api { | ||
| namespace pipeline { | ||
|
|
||
| /** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use this syntax, otherwise doxygen does not generate the documentation properly:
/// Status of image segmentation processing
enum class ImageSegmentationStatus {
UNINITIALIZED, ///< processing not initialized
INITIALIZED, ///< processing correctly initialized, but not started
IN_PROGRESS, ///< processing in progress
COMPLETED, ///< processing completed
ABORTED ///< processing aborted before completion
};If you want to test, you'll also need this change I already merged to master:
d5b6492
Without it, enum declared in undocumented namespace are simply not visible in the documentation.
| * @enum class ImageSegmentationStatus | ||
| */ | ||
| enum class ImageSegmentationStatus { | ||
| UNINITIALIZED = 0, // processing not initialized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, no need to specify each value I think, because it's probably their default value anyway.
Plus we don't really use them.
| /// @brief segmentation request from an input image | ||
| /// @param[in] image pointer to image | ||
| /// @return FrameworkReturnCode::_SUCCESS (segmentation succeeded) or FrameworkReturnCode::_ERROR_ (segmentation failed) | ||
| virtual FrameworkReturnCode segmentationRequest(SRef<Image> image) = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
I know it's been done elsewhere, but not a fan of this name:
- usually a verb is used for method (action). Here it sounds like an object
- request is redundant. If we call a method, we make a request to the object to perform an action.
It could be for example: segment(), run/performSegmentation(), or something else.
If we want to be concise, it could even be just run()-, because calling IImageSegmentationPipeline::run() it is clear enough that run() will perform an image segmentation.
Also, I'm not sure, but enum ImageSegmentationStatut could be defined inside the class, and simply be called Status. The method getStatus() is not called getImageSegmentationStatus().
Just some thoughts, you decide ;)
| @@ -0,0 +1,120 @@ | |||
| /** | |||
| * @copyright Copyright (c) 2017-2025 B-com http://www.b-com.com/ | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New file => 2025 only, no?
interfaces/datastructure/Mask2D.h
Outdated
| namespace datastructure { | ||
|
|
||
| /** | ||
| * @enum class Segmentation2DType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other comment about doxygen syntaxt for enums.
| return FrameworkReturnCode::_SUCCESS; | ||
| } | ||
|
|
||
| bool Mask2DCollection::isExistMask(uint32_t id) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isExist is not really english. contains()?
interfaces/datastructure/Mask2D.h
Outdated
| } | ||
| }; | ||
| using MaskInfoType = std::map<uint8_t, SegInfo>; | ||
| using ClassLabelType = std::map<int16_t, std::string>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this table be moved out of Mask2D? I mean, for a given segmentation process, this map is going to be the same, right ?
Or maybe not? Is this a per image thing? But in theory, it could be interesting to use a single table for all masks to not have to repeat this association int->Class in every Mask2D?
MaskInfoType is probably tied to the Mask, because being limited to 255 values, it couldn't encode a whole image sequence, so this makes more sense.
It can stay as is for now I guess, but moving it outside could be an optimization to save some memory, if need be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the map from class to label is global. for example if the model is trained with 150 classes, it is a map(int -> string) of size 150. currently a map only has 1 mask collection. the idea was to put all segmented masks in one collection which can be a combination of several segmentation models. maybe a map should have a list of mask collections (std::vector<SRef>)
interfaces/datastructure/Mask2D.h
Outdated
|
|
||
| /// @brief set Id | ||
| /// @param[in] id Mask2D ID | ||
| void setId(uint32_t id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are setters useful if the object can be entirely build with its ctor?
| return true; | ||
| } | ||
|
|
||
| SRef<const Mask2DCollection> Map::getConstMask2DCollection() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it mandatory to return an SRef? Or a simple ref would suffice?
I.e. is there a scenario where the caller will claim the ownership of the collection, so that it can work on it while the Map is destroyed? Or is the collection lifetime linked to the one of the Map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the mask collection's lifetime is not linked to one map. user can do getMask2DCollection(SRef& maskCollection) and continue to work on it even when the map had already been destroyed
return a simple ref is a good idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by your comment. You say that the collection can outlive the Map, but you still agree to return a simple ref? If so, the collection cannot be processed after the Map is gone. Maybe you were describing the state as it were, and not how it was intended to be?
| if (defineMaskId) { | ||
| newMask->setId(m_currentId++); | ||
| } | ||
| m_masks[newMask->getId()] = newMask; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thus do you think it's worth checking that the id does not already exist? Is it a warning or an error? Probably an error no?
| /// @brief This method allow to add a Mask2D to the Mask2D manager component | ||
| /// @param[in] mask the Mask2D to add to the set of persistent Mask2Ds | ||
| /// @return FrameworkReturnCode::_SUCCESS_ if the addition succeed, else FrameworkReturnCode::_ERROR. | ||
| FrameworkReturnCode addMask(SRef<Mask2D> mask); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool defineMaskId = true parameter removed here, but not from IMapManager and IMask2DManager \ addMask(), is that intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is to simplify the id management of masks. We let the user to define the ID before adding the mask into the collection. user should do mask->setId() before adding it into the collection. Then, the maskCollection will check if a mask with the same ID exists already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand your answer: if the user sets the ID, then we don't need the parameter. So you removed it from here, OK.
My remark was that this parameter was still present in MapManager and Mask2DManager version of addMask()
From what I see currently, MapManager passes defineId to Mask2DManager.addMask(), but then this parameter is ignored by Mask2DManager.addMask(). So maybe it needs to be removed from those classes as well?
As a side note, shouldn't the MaskCollection be responsible for managing the IDs? This way we wouldn't have to check it is valid? You could have MaskCollection::createMask2D() factory method for example.
Or having the addMask2D method return the ID the Collection have assigned to it. But the factory method would guarantee we don't expose a setId() method that allows anyone to change the ID.
Or another solution, don't put ID in Mask2D, and let the Collection manage the ID as the key of its internal map.
src/datastructure/Mask2D.cpp
Outdated
| return m_maskInfo; | ||
| } | ||
|
|
||
| void Mask2D::print() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe you could make a toString() that outputs the JSON, so you can reuse the same impl to print it here, and to output it in the file ?
| return FrameworkReturnCode::_ERROR_; | ||
| } | ||
| minId = m_masks.begin()->first; | ||
| maxId = (--m_masks.end())->first; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice one. I found this version for max, I'll let you pick the one you prefer (and if it works :p). There's just less syntax:
maxId = m_masks.rbegin()->first;
| * * instanceId, the instance Id of the detected object, if instanceId < 0, it means that the current pixel belongs to a "stuff" class which is uncountable, otherwise it belongs to a "thing" class | ||
| * * confidence, confidence score between 0 and 1, the confidence score of the segmentation, if confidence < 0, it means that the confidence score is not available | ||
| */ | ||
| struct SegInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep it as is for now, this PR has to move on, but I wonder whether it could be worth introducing some kind of type hierarchy here for different type of segmentation, so that we don't have these kind of struct with fields that are sometimes irrelevant. It's probably better to have things more precisely typed.
No description provided.